﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using HaiHui.Business;
using System.Web;
using System.Windows;
using System.Collections.Specialized;
using System.Diagnostics;
using HaiHui.Data;

namespace HaiHui
{
    public class HttpUtils
    {
        //private static event EventHandler<GenericEventArgs<string>> m_ReportProgress;
        //public static event EventHandler<GenericEventArgs<string>> ReportProgress
        //{
        //    add
        //    {
        //        m_ReportProgress += value;
        //    }
        //    remove
        //    {
        //        m_ReportProgress -= value;
        //    }
        //}

        //private static void OnReportProgress(string message)
        //{
        //    if (m_ReportProgress != null)
        //        m_ReportProgress(null, new GenericEventArgs<string>(message));
        //}

        //public static string ExtractViewState(string s)
        //{
        //    string viewStateNameDelimiter = "__VIEWSTATE";
        //    string valueDelimiter = "value=\"";

        //    int viewStateNamePosition = s.IndexOf(viewStateNameDelimiter);
        //    int viewStateValuePosition = s.IndexOf(
        //          valueDelimiter, viewStateNamePosition
        //       );

        //    int viewStateStartPosition = viewStateValuePosition +
        //                                 valueDelimiter.Length;
        //    int viewStateEndPosition = s.IndexOf("\"", viewStateStartPosition);

        //    return HttpUtility.UrlEncodeUnicode(
        //             s.Substring(
        //                viewStateStartPosition,
        //                viewStateEndPosition - viewStateStartPosition
        //             )
        //          );
        //}

        public static byte[] BuildPOSTData(Dictionary<string, string> parameters)
        {
            StringBuilder sb = new StringBuilder();

            bool first = true;
            foreach (string key in parameters.Keys)
            {
                if (!first)
                    sb.Append("&");
                else
                    first = false;

                sb.Append(key);
                sb.Append("=");
                sb.Append(parameters[key]);
            }

            ASCIIEncoding encoding = new ASCIIEncoding();
            return encoding.GetBytes(sb.ToString());
        }

        public static string SendPOSTForLogin(string url, Dictionary<string, string> parameters, CookieContainer cookies, string contentType)
        {

            List<object> listOfString = new List<object>();
            listOfString.Add(listOfString);

            // POST to the login form
            byte[] data = BuildPOSTData(parameters);

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = contentType;
            request.ContentLength = data.Length;
            request.CookieContainer = cookies;

            using (Stream reqStream = request.GetRequestStream())
            {
                reqStream.Write(data, 0, data.Length);
                reqStream.Close();
            }

            WebResponse response = request.GetResponse();

            using (Stream respStream = response.GetResponseStream())
            {
                Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
                using (StreamReader reader = new StreamReader(respStream))
                {
                    return reader.ReadToEnd();
                }
            }

        }


        /// <summary>
        /// intoarce html-u url-ului :)
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string Get(string url)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.CookieContainer = UserInstance.Instance.CookieContainer;

            using (Stream respStream = request.GetResponse().GetResponseStream())
            {
                //Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
                using (StreamReader reader = new StreamReader(respStream))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        
        /// <summary>
        /// Aici incepe durerea.
        /// </summary>
        /// <returns>durerea</returns>
        public static List<Album> GetAlbumList()
        {
            //return new List<Album>();

            string albumListHtml = Get(Constants.AlbumListURL);

            List<Album> albums = new List<Album>();

            int index = -1;
            do
            {
                string albumName;
                string picsUrl;
                string detailsUrl;
                int length;

                index = albumListHtml.IndexOf("'albume-foto/");
                if (index > -1)
                {
                    Album album = new Album();

                    albumListHtml = albumListHtml.Substring(index + 1);
                    length = albumListHtml.IndexOf("' title='Vizu");
                    picsUrl = String.Concat(Constants.BaseURL, albumListHtml.Substring(0, length));

                    string id = picsUrl.Replace(".html", "").Substring(picsUrl.LastIndexOf('_') + 1);
                    album.Id = Int32.Parse(id);

                    if (DataStore.Albums.Where(p => p.Id == album.Id).Count() != 0)
                    {
                        continue;
                    }

                    index = albumListHtml.IndexOf("Vizualizaţi Anunţul'><b>");
                    albumListHtml = albumListHtml.Substring(index + 24);
                    length = albumListHtml.IndexOf("</b>");
                    albumName = albumListHtml.Substring(0, length);

                    index = albumListHtml.IndexOf("use_add_album.php?");
                    albumListHtml = albumListHtml.Substring(index);
                    length = albumListHtml.IndexOf("'");
                    detailsUrl = String.Concat(Constants.BaseURL, albumListHtml.Substring(0, length));

                    
                    album.Name = albumName;
                    album.PicsUrl = picsUrl;
                    album.DetailsUrl = detailsUrl;

                    DataStore.Worker.ReportProgress(1, String.Format("Incarcam albumul \"{0}\"", album.Name));

                    album.GetDetailsData();

                    album.GetPicturesAsync();
                    albums.Add(album);
                }

            } while (index >= 0);

            return albums;
        }

        /// <summary>
        /// Oare ce face fctia asta?!
        /// </summary>
        public static string Login(string email, string password, out bool result)
        {
            UserInstance.Instance.CookieContainer = new CookieContainer();
            UserInstance.Instance.Email = email;
            UserInstance.Instance.Password = password;
            result = false;

            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("email", email);
            parameters.Add("parola", password);

            string html = HttpUtils.SendPOSTForLogin(Constants.LoginURL, parameters, UserInstance.Instance.CookieContainer, ContentTypes.applicationx_www_form_urlencoded);

            if (html.Contains("Bun venit!"))
                result = true;
            else
                result = false;

            return html;
        }


        public static List<Country> GetCountries()
        {
            List<Country> countries = new List<Country>();

            string html = Get(Constants.AddNewAlbumURL);

            int countryId;
            string countryName;

            string startPattern = String.Empty;
            string endPattern = String.Empty;
            int index, length;

            startPattern = "select name='id_tara'";
            endPattern = "<select name='id_localitate'";
            index = html.IndexOf(startPattern);
            html = html.Substring(index);
            length = html.IndexOf(endPattern);

            html = html.Substring(0, length);

            do
            {

                startPattern = "<option value='";
                endPattern = "'";

                index = html.IndexOf(startPattern);
                if (index > -1)
                {
                    html = html.Substring(index + startPattern.Length);
                    length = html.IndexOf(endPattern);

                    countryId = Int32.Parse(html.Substring(0, length));

                    startPattern = ">";
                    endPattern = "<";
                    countryName = Utils.ScrapeNext(ref html, startPattern, endPattern);

                    countries.Add(new Country() { Id = countryId, Name = countryName });
                }

            } while (index > -1);
            

            return countries;
        }

        public static List<City> GetCities(int countryId)
        {
            //POST with country id to get the list of cities.

            Dictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("id_tara", countryId.ToString());

            string html = SendPOST(Constants.AddNewAlbumURL, parameters);



            List<City> cities = new List<City>();

            int cityId;
            string cityName;

            string startPattern = String.Empty;
            string endPattern = String.Empty;
            int index, length;

            startPattern = "select name='id_localitate'";
            endPattern = "<input type=\"text\" name=\"add_loc\"";
            index = html.IndexOf(startPattern);
            html = html.Substring(index);
            length = html.IndexOf(endPattern);

            html = html.Substring(0, length);

            do
            {

                startPattern = "<option value='";
                endPattern = "'";

                index = html.IndexOf(startPattern);
                if (index > -1)
                {
                    html = html.Substring(index + startPattern.Length);
                    length = html.IndexOf(endPattern);

                    if (!Int32.TryParse(html.Substring(0, length), out cityId))
                        continue;

                    startPattern = ">";
                    endPattern = "<";
                    cityName = Utils.ScrapeNext(ref html, startPattern, endPattern);

                    cities.Add(new City() { Id = cityId, Name = cityName });
                }

            } while (index > -1);


            return cities;
        }

        /// <summary>
        /// Submit-uieste cu POST url-ul
        /// 
        /// Trimite campurile specificate in parametrul "nvc", 
        /// si de asemenea trimite si fisierul (daca exista)
        /// </summary>
        /// <returns>html-ul rezultat</returns>
        public static string SendPOSTWithFile(string url, string file, Dictionary<String, String> nvc)
        {

            long length = 0;
            string boundary = "----------------------------" +
            DateTime.Now.Ticks.ToString("x");


            HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
            httpWebRequest2.ContentType = "multipart/form-data; boundary=" +
            boundary;
            httpWebRequest2.Method = "POST";
            httpWebRequest2.KeepAlive = true;
            httpWebRequest2.Credentials = System.Net.CredentialCache.DefaultCredentials;
            httpWebRequest2.Referer = url;
            httpWebRequest2.CookieContainer = UserInstance.Instance.CookieContainer;



            Stream memStream = new System.IO.MemoryStream();

            byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
            boundary + "\r\n");


            string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

            foreach (string key in nvc.Keys)
            {
                string formitem = string.Format(formdataTemplate, key, nvc[key]);
                byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
                memStream.Write(formitembytes, 0, formitembytes.Length);
            }


            memStream.Write(boundarybytes, 0, boundarybytes.Length);

            string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: image/jpeg\r\n\r\n";

            string header = string.Format(headerTemplate, "poza", file.Substring(file.LastIndexOf('\\')+1));
            byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
            memStream.Write(headerbytes, 0, headerbytes.Length);

            if (!string.IsNullOrEmpty(file))
            {

                FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
                byte[] buffer = new byte[1024];

                int bytesRead = 0;
                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    memStream.Write(buffer, 0, bytesRead);
                }


                memStream.Write(boundarybytes, 0, boundarybytes.Length);
                fileStream.Close();
            }
            httpWebRequest2.ContentLength = memStream.Length;

            Stream requestStream = httpWebRequest2.GetRequestStream();

            memStream.Position = 0;
            byte[] tempBuffer = new byte[memStream.Length];
            memStream.Read(tempBuffer, 0, tempBuffer.Length);
            memStream.Close();
            requestStream.Write(tempBuffer, 0, tempBuffer.Length);
            requestStream.Close();


            WebResponse webResponse2 = httpWebRequest2.GetResponse();

            Stream stream2 = webResponse2.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);

            string responseString = reader2.ReadToEnd();

            webResponse2.Close();
            httpWebRequest2 = null;
            webResponse2 = null;

            return responseString;

        }

        /// <summary>
        /// sumbituieste url-ul cu parametrii primiti.
        /// </summary>
        public static string SendPOST(string url, Dictionary<String, String> parameters)
        {
            return SendPOSTWithFile(url, "", parameters);
        }

    }



}
